#include "VectorLayer.h"
#include <QFileInfo>
#include <gdal/gdal_priv.h>
#include <gdal/ogr_geometry.h>
#include <gdal/ogrsf_frmts.h>
#include <QPainter>
#include <TGS/MapControl2.0/RenderContext.h>

VectorLayer::VectorLayer(const QString& filePath, ReadingProgressFun fun)
	: MapLayer(MapLayer_Vector)
	, _filePath(filePath)
	, _boundaryColor(Qt::black)
	, _selectColor(Qt::red)
	, _readingProgressFun(fun)
{
	openFile(filePath);

	QFileInfo fileInfo(filePath);
	QString fileName = fileInfo.completeBaseName();
	setName(fileName);
}


VectorLayer::~VectorLayer(void)
{
}

void VectorLayer::openFile( const QString& filePath )
{
	::OGRRegisterAll();
	OGRDataSource* dataSource = OGRSFDriverRegistrar::Open(filePath.toStdString().c_str(), FALSE );
	if(nullptr == dataSource) return;

	OGRLayer  *layer = dataSource->GetLayer(0);
	if(nullptr == layer) 
	{
		OGRDataSource::DestroyDataSource(dataSource);
		return;
	}

	layer->ResetReading();
	OGRFeature *feature = nullptr;
	int featureCount = layer->GetFeatureCount();
	int index = 0;
	while ((feature = layer->GetNextFeature()) != NULL)
	{
		int percent = (++index) / (double) featureCount * 100;
		if(_readingProgressFun) _readingProgressFun(percent);
		
		OGRGeometry *geometry = feature->GetGeometryRef();	
		if (geometry == nullptr) continue;
		if(geometry->getGeometryType() == wkbPolygon)
		{
			OGRPolygon* ogrPolygon = (OGRPolygon*)(geometry);
			Polygon polygon;
			for (int i = 0; i < ogrPolygon->getExteriorRing()->getNumPoints(); ++i)
			{
				OGRPoint point;
				ogrPolygon->getExteriorRing()->getPoint(i, &point);
				polygon.appendPoint(point.getX(), point.getY());
			}
			Envelope envelope = polygon.getEnvelope();
			_envelope.expandToInclude(envelope);
			_polygons[feature->GetFID()] = polygon;
			_polygonAreas[feature->GetFID()] = polygon.getAera();
			double min[] = {envelope.getMinX(), envelope.getMinY()};
			double max[] = {envelope.getMaxX(), envelope.getMaxY()};
			_polygonTree.Insert(min, max, feature->GetFID());
			_featureIds.push_back(feature->GetFID());
		}
		

		OGRFeature::DestroyFeature(feature);
	}


	OGRDataSource::DestroyDataSource(dataSource);
}

void VectorLayer::render( RenderContext* renderContext )
{
	if(!isVisible()) return;

	renderContext->painter()->save();

	QPolygon onePixPolygon;
	onePixPolygon.append(QPoint(0, 0));
	onePixPolygon.append(QPoint(2, 0));
	onePixPolygon.append(QPoint(2, 2));
	onePixPolygon.append(QPoint(0, 2));
	Polygon mapPolygon = renderContext->mapToPixel().screenToMap(onePixPolygon);
	double minArea = mapPolygon.getAera();

	Envelope mapEnvelope = renderContext->extent();
	double min[] = { mapEnvelope.getMinX(), mapEnvelope.getMinY() };
	double max[] = { mapEnvelope.getMaxX(), mapEnvelope.getMaxY() };
	auto searchResult = _polygonTree.Search(min, max);
	for (size_t i = 0; i < searchResult.size(); ++i)
	{
		FeatureId featureId = searchResult[i];
		if(_polygonAreas[featureId] < minArea)
		{
			continue;
		}
		QPen pen = renderContext->painter()->pen();
		pen.setColor(_boundaryColor);
		pen.setWidth(1);
		if(_selectedPolygonId.end() != _selectedPolygonId.find(featureId))
		{
			pen.setColor(_selectColor);
			pen.setWidth(3);
		}
		renderContext->painter()->setPen(pen);
		QPolygon polygon = renderContext->mapToPixel().mapToScreen(_polygons[featureId]);
		renderContext->painter()->drawPolygon(polygon);
	}

	renderContext->painter()->restore();
}

VectorLayer::Envelope VectorLayer::getEnvelope() const
{
	if(!isVisible()) return Envelope();
	return _envelope;
}

void VectorLayer::setSelectPolygon( const Polygon& selectPolygon )
{
	if(!isVisible()) return;

	Envelope envelope = selectPolygon.getEnvelope();
	double min[] = { envelope.getMinX(), envelope.getMinY() };
	double max[] = { envelope.getMaxX(), envelope.getMaxY() };
	auto searchResult = _polygonTree.Search(min, max);
	for (size_t i = 0; i < searchResult.size(); ++i)
	{
		if(selectPolygon.isIntersect(_polygons[searchResult[i]]))
		{
			if(SelectType_PositiveSelect == _selectType)
			{
				_selectedPolygonId.insert(searchResult[i]);
			}
			else
			{
				_selectedPolygonId.erase(searchResult[i]);
			}
			
		}
	}
}

void VectorLayer::setSelectPoint( const Point& selectPoint )
{
	if(!isVisible()) return;

	double min[] = { selectPoint.getX(), selectPoint.getY() };
	double max[] = { selectPoint.getX(), selectPoint.getY() };
	auto searchResult = _polygonTree.Search(min, max);
	for (size_t i = 0; i < searchResult.size(); ++i)
	{	
		if(!_polygons[searchResult[i]].contain(selectPoint)) continue;

		if(SelectType_PositiveSelect == _selectType)
		{
			_selectedPolygonId.insert(searchResult[i]);
		}
		else
		{
			_selectedPolygonId.erase(searchResult[i]);
		}
	}
}

void VectorLayer::deselect()
{
	_selectedPolygonId.clear();
}

void VectorLayer::removePolygon( const std::set<FeatureId>& polygonFeatureIds )
{
	for (auto iter = polygonFeatureIds.begin(); iter != polygonFeatureIds.end(); ++iter)
	{
		_selectedPolygonId.erase(*iter);
		_polygonAreas.erase(*iter);

		auto findIter = _polygons.find(*iter);
		if(_polygons.end() == findIter) continue;

		Envelope envelope = findIter->second.getEnvelope();
		double min[] = { envelope.getMinX(), envelope.getMinY() };
		double max[] = { envelope.getMaxX(), envelope.getMaxY() };
		_polygonTree.Remove(min, max, findIter->first);
		_polygons.erase(*iter);
	}
}

void VectorLayer::clearSelectedPolygon()
{
	_selectedPolygonId.clear();
}
